import path from 'node:path';
import process from 'node:process';
import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite';
import { getProxy } from '@peng_kai/kit/vite';
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
import externalGlobals from 'rollup-plugin-external-globals';
import { visualizer } from 'rollup-plugin-visualizer';
import UnoCSS from 'unocss/vite';
import AutoImport from 'unplugin-auto-import/vite';
import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers';
import Components from 'unplugin-vue-components/vite';
import { defineConfig, type HtmlTagDescriptor, loadEnv, type Plugin } from 'vite';
import { createHtmlPlugin } from 'vite-plugin-html';
import { VitePWA } from 'vite-plugin-pwa';
import tsAlias from 'vite-plugin-ts-alias';
import VueDevTools from 'vite-plugin-vue-devtools';

// PostCSS
import autoprefixer from 'autoprefixer';
import postcssPresetEnv from 'postcss-preset-env';

// "build": "vue-tsc -b && vite build",
const ENV_DIR = './envs';

export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, ENV_DIR) as ImportMetaEnv;
  const proxys = getProxy(env);
  const isProd = mode === 'production';
  const isStg = mode === 'staging';
  const isDev = mode === 'development';

  return {
    envDir: ENV_DIR,
    define: {
      '__APP_VERSION__': `'${process.env.npm_package_version}'`,
      'import.meta.env.VERSION': `"${Date.now()}"`,
    },
    server: {
      host: true,
      port: Number(env.VITE_PORT),
      proxy: {
        ...proxys,
        '^/g/(.+)/(api|ws)': {
          target: 'https://img.g9aaa.com',
          // target: 'ws://192.168.2.103:9980',
          changeOrigin: true,
          ws: true,
        },
      },
    },
    build: {
      target: ['chrome70', 'safari14', 'firefox68'],
      reportCompressedSize: true,
      minify: 'terser',
      // sourcemap: 'hidden',
      terserOptions: {
        compress: {
          drop_console: env.VITE_DROP_CONSOLE === '1',
          drop_debugger: true,
        },
      },
      rollupOptions: {
        external: ['echarts', 'lottie-web', '@tonconnect/ui'],
        plugins: [
          externalGlobals({
            // 通过 CDN 引入的 ECharts，看index.html中的引入
            'echarts': 'echarts',
            'lottie-web': 'lottie',
            '@tonconnect/ui': 'TON_CONNECT_UI',
          }),
          // PWA配置
          VitePWA({
            registerType: 'autoUpdate', // 自动更新缓存文件
            // injectRegister: 'script', // service-work内容生成模式
            strategies: 'generateSW', // 使用 Workbox 生成 Service Worker
            // srcDir: '/js/',
            // filename: 'service-worker.js',
            devOptions: {
              enabled: false,
            },
            manifest: false,
            workbox: {
              maximumFileSizeToCacheInBytes: 4000000,
              // globPatterns: ['**/*.{js,css,html,ico,png,svg,ts,tsx}'], // 缓存所有静态资源
              // runtimeCaching: [{
              //   urlPattern: /\.html$/,
              //   handler: 'NetworkFirst', // 对 HTML 文档使用网络优先策略
              // }],
            },
          }),
        ],
        input: {
          main: path.resolve('index.html'),
          agent: path.resolve('agent.html'),
          pwa: path.resolve('pwa.html'),
        },
        onwarn: (warning, warn) => {
          if (['CIRCULAR_DEPENDENCY', 'CYCLIC_CROSS_CHUNK_REEXPORT'].includes(warning.code!)) {
            return;
          }
          warn(warning);
        },
      },
    },
    plugins: [
      vue({
        template: {
          compilerOptions: {
            isCustomElement: tag => tag.startsWith('swiper-'),
          },
        },
      }),
      vueJsx(),
      UnoCSS({ inspector: true }),
      globalDefinePlugin(),
      visualizer(),
      VueDevTools(),
      // splitVendorChunkPlugin(),
      tsAlias({ tsConfigName: 'tsconfig.app.json' }),
      AutoImport({
        dts: 'src/types/auto-imports.d.ts',
        vueTemplate: true,
        imports: ['vue', 'vue-router'],
        dirs: [path.resolve('src/auto-import')],
      }),
      Components({
        dts: 'src/types/components.d.ts',
        dirs: [],
        globs: [],
        resolvers: [
          // Antd 组件（AXxx）
          AntDesignVueResolver({ importStyle: false }),
          // 本项目组件（TXxx）
          {
            type: 'component' as const,
            resolve: name => name.match(/^T[A-Z]/) && { name: name.replace(/^T/, ''), from: '~/auto-import/components' },
          },
          // {
          //   type: 'directive' as const,
          //   resolve: (name) => name.match(/^D[A-Z]/) && { name, from: '~/auto-import/directives' },
          // }
        ],
      }),
      VueI18nPlugin({
        runtimeOnly: true,
        compositionOnly: true,
        fullInstall: true,
        include: [path.resolve('src/modules/locale/**/appMessage.json')],
      }),
      createHtmlPlugin({
        inject: {
          tags: [
            ...(!isProd ? getErudaCode() : []),
          ],
        },
      }),
      // sentryVitePlugin({
      //   org: 'ma-sy',
      //   project: 'gam',
      //   authToken: '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',
      // }),
    ],
    css: {
      preprocessorOptions: {
        scss: {
          api: 'modern-compiler',
        },
      },
      postcss: {
        plugins: [
          autoprefixer() as any,
          postcssPresetEnv() as any,
        ],
      },
    },
  };
});

function getErudaCode(): HtmlTagDescriptor[] {
  return [
    { tag: 'script', attrs: { src: '//cdn.jsdelivr.net/npm/eruda' }, injectTo: 'head-prepend' },
    { tag: 'script', children: '/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) && eruda.init()', injectTo: 'body' },
  ];
}

/**
 * 将 define 中以 __APP_ 开头的变量挂载到 window 对象上
 */
function globalDefinePlugin(): Plugin {
  let variables = {};
  return {
    name: 'vite-plugin-global-define',
    apply: 'build',
    configResolved(resolvedConfig) {
      const define = resolvedConfig.define;
      variables = Object.entries(define ?? {})
        .filter(([key]) => key.startsWith('__APP_'))
        .reduce((acc, [key, value]) => {
          acc[key] = value;
          return acc;
        }, {} as Record<string, string>);
    },
    transformIndexHtml(html) {
      const content = Object.entries(variables).map(([k, v]) => `window.${k} = ${v}`).join(';');
      return html.replace('<head>', `<head>\n<script>${content};</script>`);
    },
  };
}
